package cn.wolfcode.service.impl;

import cn.wolfcode.domain.User;
import cn.wolfcode.domain.vo.UserVo;
import cn.wolfcode.mapper.UserMapper;
import cn.wolfcode.service.IUserService;
import cn.wolfcode.util.PasswordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.UUID;

/**
 * 登录接口实现类
 */
@Service    // 语义化注解：与 Controller 功能一致，只不过名字不同。
// 更加能够让我们见名之意。将当前类创建对象纳入到 Spring 容器中
public class UserServiceImpl implements IUserService {

    // 调用 UserMapper 去数据库查询
    @Autowired  // 在 Spring 容器中拿出对象(Bean)
    private UserMapper userMapper;

    @Override
    public Mono<UserVo> login(User user) {
        // 对参数验证，若传递的 user 是空，则登录失败。
        if(user == null){
            return Mono.empty();
        }
        // 判断，若你的用户名或密码有任意一个位 Null 则直接不用验证，登录失败。
        if(user.getUsername() == null || user.getPassword() == null){
            // 登录失败,返回一个空。
            return Mono.empty();
        }
        // 验证用户名和密码的长度不能小于4位
        if(user.getUsername().length() < 4 || user.getPassword().length() < 4){
            // 用户名或密码长度 < 4 位，登录失败，返回 Null
            return Mono.empty();
        }
        // 前台传递的用户名 admin 密码 123456
        // 数据库中存储用户名 admin  密码 5550E495D4BDB8783C5C9554BA717E82
        // 因为前台传递的是明文密码，后端数据库中存储的是经过加密的密码。所以不能直接比对。
        // 1. 根据用户名去数据库中将当前用户的数据都查询出来
        User currentUser = userMapper.checkUsername(user.getUsername());
        if(currentUser == null){
            // 若没查询到说明用户名填写错误。登录失败
            return Mono.empty();
        }
        // 2. 若查询到了，id username password salt。我们使用前台传递的明文密码 + 盐生成密文密码（MD5）。
            // 使用我们自己书写好的工具类。将前台传递的明文密码 + 数据库中查询到的盐 = 密文密码。 加密2次
        String requestPassword =
                PasswordUtil.md5(PasswordUtil.md5(user.getPassword() + currentUser.getSalt()));
        // 3.在用加密后的密码 与 数据库中查询出来的 password（密文密码进行比对）
            // 若不一致则说明密码错误。登录失败
        if(!requestPassword.equals(currentUser.getPassword())){
            // 说明密码错误
            return Mono.empty();
        }
        // 4.若都一致，我们还需要生成一个 32 位的随机数，作为 Token 封装到 UserVo 对象中。作为登录的令牌
        // 生成的 token 会存在 -  我们不需要横线， replaceAll("-","") 将横线替换成空串。 123-456-789  123456798
        String token = UUID.randomUUID().toString().replaceAll("-","");
        // 5. 封装 id 和 用户名。 （数据库中查询出来的） 就是为了不封装密码和盐
        UserVo userVo = new UserVo();
        userVo.setId(currentUser.getId());
        userVo.setUsername(currentUser.getUsername());
        userVo.setToken(token);
        // 6. 将结果封装到 Mono 对象中并返回。
        // just 方法适合的。 就是将我们封装好的数据放入到里面。 就存在了数据1.
        return Mono.just(userVo);
    }
}
